#include "mainwindow.h"
#include "mydialog.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include "meshelper.h"
#include "sysinfothread.h"
#include "tool.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
//    if(getSetting("agingResult").toBool()){
//        MyDialog dlg;
//        dlg.setType(typeOk);
//        dlg.setContent("本机老化已完成,\n请联网过站");
//        dlg.exec();
//    }
    loadItems();
    loadSlots();
    loadOtherInfo();
}

MainWindow::~MainWindow()
{
    delete ui;
    if (p->state() == QProcess::Running){
        p->terminate();
        p->waitForFinished();
    }
    delete p;
    for (int i = 0; i < tasks.length(); ++i) {
        delete tasks.at(i);
    }
    tasks.clear();
}

void MainWindow::enterRebootMode()
{
    if(getSetting("agingResult").toBool()){
        logD("弹窗提醒过站2:enterRebootMode");
        MyDialog dlg;
        dlg.setType(typeOk);
        dlg.setContent("本机老化已完成,\n请联网过站");
        dlg.exec();
        return;
    }
    qDebug()<<"enterRebootMode";
    QProcess p;
    //显示当前重启次数
    p.start(ROOT_PATH + "/script/reboot/rebootInfo.sh count");
    p.waitForFinished();
    QString count = p.readAll().simplified();
    qDebug()<<"当前重启次数:"<<count;
    ui->infoBoard->append("当前重启次数："+count);
    //显示当前重启老化测试剩余多少时间
    p.start(ROOT_PATH + "/script/reboot/rebootInfo.sh remainTime");
    p.waitForFinished();
    QString remainTime = p.readAll().simplified();
    qDebug()<<"重启剩余时长:"<<remainTime;
    ui->infoBoard->append("重启剩余时长："+remainTime+"分钟");
    //显示单次重启耗时，是否超过了阈值（若超过了，则老化失败）
    p.start(ROOT_PATH + "/script/reboot/rebootInfo.sh oneRebootTime");
    p.waitForFinished();
    QString timeCost = p.readAll().simplified();
    qDebug()<<"本次重启耗时:"<<timeCost+"秒";
    ui->infoBoard->append("本次重启耗时:"+timeCost+"秒");
    int stdSec = getSetting("stdRebootTimeCost").toInt();
    if(timeCost.toInt() < stdSec){//单次重启未超时，继续老化
        doWork();
    }else{//重启超时了，检查原因
        ui->infoBoard->append("<font color=red>单次重启耗时过长（标准"+QString::number(stdSec)+"秒）</font>");

        //判断是否存在CPU和内存测试
        bool checkCpu=false;
        bool checkMem=false;
        Task *task;
        for (int i = 0; i < tasks.length(); ++i) {
            task = tasks.at(i);
            if(task->name.contains("CPU")){
                checkCpu = true;
            }else if(task->name.contains("内存")){
                checkMem = true;
            }
        }
        if(checkCpu){
            //检查CPU测试是否完整
            if(readFile(QString("%1/work/cpuFlag.txt").arg(ROOT_PATH)).contains("over")){
                ui->infoBoard->append("CPU测试有结束标志");
                qDebug()<<"CPU测试有结束标志";
            }else{
                ui->infoBoard->append("未找到CPU测试结束标志");
                testFail("未找到CPU测试结束标志");
                return;
            }
        }
        if(checkMem){
            //检查内存测试是否完整
            if(readFile(QString("%1/work/memFlag.txt").arg(ROOT_PATH)).contains("over")){
                ui->infoBoard->append("内存测试有结束标志");
                qDebug()<<"内存测试有结束标志";
            }else{
                ui->infoBoard->append("未找到内存测试结束标志");
                testFail("未找到内存测试结束标志");
                return;
            }
        }

        //未找到CPU和内存测试的原因
        testFail("单次重启耗时过长（标准"+QString::number(stdSec)+"秒）");
    }

}

void MainWindow::enterBookedMode()
{
    qDebug()<<"enterBookedMode, 删除预定图标";
    QProcess p;
    p.execute(ROOT_PATH+"/script/reboot/delete_desktop.sh");
    on_pushButton_clicked();
}

bool MainWindow::loadTaskFromConfig(QList<Task *> *tasks, QString config)
{
    //若tasks不为空，则清除其中每个指针的内存空间，并删除所有指针变量
    if (!tasks->isEmpty()){
        for(int i=0; i<tasks->length(); ++i){
            delete tasks->at(i);
        }
        tasks->clear();
    }
    QString configName = ROOT_PATH + "/conf/" + config;
    if(!QFile(configName).exists()){
        qDebug()<<"配置文件未找到";
        return false;
    }
    QSettings settings(configName, QSettings::IniFormat);
    settings.setIniCodec("UTF-8");
    QStringList groups = settings.childGroups();
    for (int i=0; i<groups.size(); i++)
    {
        settings.beginGroup(groups.at(i));

        bool ischeck = settings.value("ischeck").toBool();
        if (ischeck){
            Task * task = new Task();
            task->name = settings.value("name").toString();
            task->preset = settings.value("preset").toString();
            task->script = settings.value("script").toString();
            task->stop_script = settings.value("stop_script").toString();
            task->group = groups.at(i);
            tasks->append(task);
        }

        settings.endGroup();
    }
    return true;
}

void MainWindow::loadItems()
{
    // 获取任务集
    loadTaskFromConfig(&tasks, "aging.ini");
    // 设置table
    ui->tableWidget->clear();
    ui->tableWidget->setRowCount(tasks.length());
    QStringList headers;
    headers<<"测试项"<<"参数"<<"状态";
    ui->tableWidget->setHorizontalHeaderLabels(headers);
//    ui->tableWidget->verticalHeader()->setDefaultSectionSize(40);
    ui->tableWidget->horizontalHeader()->setStretchLastSection(false);

    //设置单元格数据
    Task *task;
    for (int i = 0; i < tasks.length(); ++i) {
        task = tasks.at(i);
        task->id = i;
        ui->tableWidget->setItem(i, 0, new QTableWidgetItem(task->name));
        ui->tableWidget->setItem(i, 1, new QTableWidgetItem(task->preset));
    }
    //调整table
    ui->tableWidget->resizeColumnsToContents();
    ui->tableWidget->horizontalHeader()->resizeSection(0, 150);
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
}

void MainWindow::loadSlots()
{
    p = new QProcess(this);
    connect(p, &QProcess::readyReadStandardOutput, this, &MainWindow::onReadyReadStandardOutput);
    connect(p, &QProcess::readyReadStandardError, this, &MainWindow::onReadyReadStandardError);
    connect(p, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &MainWindow::onProcessFinished);
    //启用右键菜单，单独测试功能
    ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, [=](const QPoint &pos){
        int row = ui->tableWidget->rowAt(pos.y());
        if(isAutoMode){
            appendLog("当前测试还未结束，请先停止测试", RED);
            return;
        }
        if(row >= 0){
            isAutoMode = false;
            QMenu menu;
            QAction *action = menu.addAction("测试");
            connect(action, &QAction::triggered, [=](){
                cid = row;
                doTask(row);
            });
            menu.exec(ui->tableWidget->mapToGlobal(pos));
        }
    });
    //配置完成后刷新数据
    connect(&settingDlg, &SettingDialog::settingFinished, this, &MainWindow::onSettingFinished);
}

void MainWindow::loadOtherInfo()
{
    qDebug()<<"loadOtherInfo";
    ui->infoBoard->append("CPU温度标准："+getSetting("cpuTemp").toString());
    ui->label_3->setText(execShell(ROOT_PATH + "/tools/getSn.sh"));
    ui->groupBox->setTitle(QString("重启老化（时长：%1分钟）").arg(getSetting("rebootTotalTime").toInt()));
    ui->groupBox_2->setTitle(QString("视频老化（时长：%1分钟）").arg(getSetting("videoTotalTime").toInt()));
    ui->tableWidget_2->setRowCount(1);
    ui->tableWidget_2->setItem(0, 0, new QTableWidgetItem("视频播放"));

    //系统信息
    ui->label_4->setText("CPU：100%");
    QString memTotal = execShell("free | awk 'NR==2{print $2/1024}'");
    ui->label_9->setText("内存："+memTotal+"M");
    sysInfoThread = new SysInfoThread();
//    connect(sysInfoThread, &SysInfoThread::tempError, this, &MainWindow::onTempError);
    connect(sysInfoThread, &SysInfoThread::finished, [&](){
        //显示CPU占用率
        ui->label_5->setText("CPU占用率："+sysInfoThread->cpuUsed+"%");
        //显示空闲内存大小
        ui->label_10->setText("内存空闲："+sysInfoThread->memFree+"M");
        //显示CPU温度
        QString cpuTemp = sysInfoThread->cpuTemp;
        ui->label_8->setText("CPU温度："+sysInfoThread->cpuTemp+"℃");

    });
    timer = new QTimer();
    timer->setInterval(3000);
    connect(timer, &QTimer::timeout, [&](){
        sysInfoThread->start();
    });
    timer->start();
}

void MainWindow::doTask(int id)
{
    if (id >= tasks.length()) return;
    ui->tableWidget->setItem(id, 2, new QTableWidgetItem(TESTING));
    QString script = tasks.at(id)->script;
    QString preset = tasks.at(id)->preset;
    QString cmd = QString("%1/script/%2 %3").arg(ROOT_PATH).arg(script).arg(preset);
//    qDebug()<<"cmd"<<cmd;
    appendLog("");
    appendLog("---------" + tasks.at(id)->name + "---------");
    p->setObjectName(QString::number(id));
    p->start(cmd);
}

void MainWindow::doWork()
{
    if (p->state() == QProcess::Running){
        appendLog("当前进程正在执行，请先停止", RED);
        return;
    }
    QPair<bool, QString> p = doWorkCheck();
    if (!p.first){
        QMessageBox::StandardButton result =
                QMessageBox::question(nullptr, "询问", p.second + ", 是否继续测试？");
        if (result != QMessageBox::Yes){
            return;
        }
    }
    clearTestInfo();
    if (timer != nullptr){
        if(!timer->isActive()){
            qDebug()<<"信息监听已停止，重启启动";
            timer->start();
        }
    }
    cid = 0;
    isAutoMode = true;
    doTask(cid);
}

void MainWindow::stopWork()
{
    if (p->state() == QProcess::Running){
        QTableWidgetItem *item = new QTableWidgetItem(NO);
        item->setTextColor(Qt::red);
        item->setTextAlignment(Qt::AlignCenter);
        if(p->objectName() == "video"){
            ui->tableWidget_2->setItem(0, 2, item);
        }else{
            ui->tableWidget->setItem(cid, 2, item);
            tasks.at(cid)->result = NO;
            isAutoMode = false;
        }
        appendLog("停止当前任务");
        //该处必须放在isAutoMode变量后，防止进出结束后继续进行下一个测试
        p->terminate();
        p->waitForFinished();
    }else{
        appendLog("当前没有任务在运行");
    }
    //自带退出脚本的测试项需要特殊的退出方式
    QString stopScript = tasks.at(cid)->stop_script;
    if (!stopScript.isEmpty()){
        QProcess::startDetached(ROOT_PATH + "/script/"+stopScript);
    }
    //手动停止任务时，有可能存在开机自启desktop，尝试删除
    QProcess::startDetached(ROOT_PATH+"/script/reboot/delete_desktop.sh");
}

void MainWindow::onTempError(QString errorInfo)
{
    qDebug()<<errorInfo;
    ui->label_8->setStyleSheet("color:red");
    ui->label_8->setText(errorInfo);
    timer->stop();
    stopWork();
    testFail(errorInfo);
}

QPair<bool, QString> MainWindow::doWorkCheck()
{
    return QPair<bool, QString>(true, "");
}

void MainWindow::clearTestInfo()
{
    ui->logView->clear();
    for (int i=0; i<ui->tableWidget->rowCount(); ++i){
        ui->tableWidget->setItem(i, 2, new QTableWidgetItem(""));
    }
}

void MainWindow::appendLog(QString log, QString color)
{
    qDebug()<<logD(log);
    ui->logView->append(QString("<font color=%1>%2</font>").arg(color).arg(log));
}

void MainWindow::startVideoTest()
{
    qDebug()<<"startVideoTest";
    p->setObjectName("video");
    p->start(QString("%1/script/video/videoplay.sh %2").arg(ROOT_PATH).arg(getSetting("videoTotalTime").toInt()));
}

void MainWindow::testFail(QString error)
{
    qDebug()<<error;
    isAutoMode = false;
    QProcess::startDetached(ROOT_PATH+"/script/reboot/delete_desktop.sh");
    MyDialog myDlg;
    myDlg.setContent(error);
    myDlg.exec();
}

void MainWindow::uploadReport(bool result)
{
    ui->infoBoard->append(logD("正在提交报告.."));
    QProcess p;
    p.start(ROOT_PATH+"/tools/minio.sh");
    p.waitForFinished();
    if(p.exitCode() == 0){
        ui->infoBoard->append(logD("报告上传成功"));
        //过站
        if(result){
            ui->infoBoard->append("正在请求mes过站..");
            bool isOk = MesHelper::updateMesInfo();
            if(isOk){
                ui->infoBoard->append("过站请求成功");
                QProcess::startDetached(ROOT_PATH+"/script/reboot/delete_desktop.sh");
                ui->infoBoard->append("取消开机自启动");
                QMessageBox::information(nullptr, "信息", "过站成功");
            }else{
                ui->infoBoard->append("过站请求失败");
            }
        }else{
            QMessageBox::warning(nullptr, "警告", logD("老化未成功，不允许过站！"));
        }
    }else{
        ui->infoBoard->append("报告上传失败");
    }
//    QString details = readFile(ROOT_PATH + "/log.txt");
//    bool flag = MesHelper::commitReport(result, details);
//    if(flag){
//        ui->infoBoard->append("报告上传成功");
//        //过站
//        if(result){
//            ui->infoBoard->append("正在请求mes过站..");
//            bool isOk = MesHelper::updateMesInfo();
//            if(isOk){
//                ui->infoBoard->append("过站请求成功");
//                QProcess::startDetached(ROOT_PATH+"/script/reboot/delete_desktop.sh");
//                ui->infoBoard->append("取消开机自启动");
//                QMessageBox::information(nullptr, "信息", "过站成功");
//            }else{
//                ui->infoBoard->append("过站请求失败");
//            }
//        }else{
//            QMessageBox::warning(nullptr, "警告", "老化未成功，不允许过站！");
//        }
//    }else{
//        ui->infoBoard->append("报告上传失败");
//    }
}


void MainWindow::onReadyReadStandardOutput()
{
    while(p->canReadLine()){
        QString info = p->readLine().simplified();
        appendLog(info);
    }
}

void MainWindow::onReadyReadStandardError()
{
    QString info = p->readAllStandardError().simplified();
    appendLog(info);
}

void MainWindow::onProcessFinished(int code)
{
    if(p->objectName() == "video"){
        qDebug()<<"code:"<<code;
        MyDialog myDlg;
        if(code == 0){
            commitSetting("agingResult", true);
            isAutoMode = false;
//            QProcess::startDetached(ROOT_PATH+"/script/reboot/delete_desktop.sh");
            myDlg.setType(typeOk);
            myDlg.setContent("视频结束，老化完成");
            myDlg.exec();
        }else{
            testFail("视频老化出错");
        }
    }else{
        bool flag = code == 0;
        QString result = code == 0 ? YES : NO;
        QTableWidgetItem *item = new QTableWidgetItem(result);
        item->setTextColor(code == 0 ? Qt::darkGreen : Qt::red);
        item->setTextAlignment(Qt::AlignCenter);
        ui->tableWidget->setItem(cid, 2, item);
        tasks.at(cid)->result = result;//记录测试结果
//        //内存测试结束时记录一下CPU温度
//        if(tasks.at(cid)->name.contains("内存")){
//            qDebug()<<"内存测试结束,"<<ui->label_8->text();
//        }
        //每项测试结束时都记录一下CPU温度
        appendLog(ui->label_8->text());
        if (isAutoMode){
            if(flag){
                if(++cid >= tasks.length()){
                    cid = 0;
                    isAutoMode = false;
                    startVideoTest();

                }else{
                    doTask(cid);
                }
            }else{
                testFail(tasks.at(cid)->name+"出错");
            }
        }

    }
}

void MainWindow::onSettingFinished()
{
    ui->infoBoard->append("配置有更新");
    ui->groupBox->setTitle(QString("重启老化（时长：%1分钟）").arg(getSetting("rebootTotalTime").toInt()));
    ui->groupBox_2->setTitle(QString("视频老化（时长：%1分钟）").arg(getSetting("videoTotalTime").toInt()));
    ui->infoBoard->append("CPU温度标准："+getSetting("cpuTemp").toString());
}


void MainWindow::on_pushButton_clicked()
{
    clearLog();
    logD("开始老化记录 -- SN:"+getSn()+" MAC:"+getHostMacAddress());
    QString cmd = ROOT_PATH + "/script/reboot/readyReboot.sh " + getSetting("rebootTotalTime").toString();
    qDebug()<<logD(cmd);
    QProcess::execute(cmd);
    QString startTime = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
    qDebug()<<logD("开始时间："+startTime);
    commitSetting("startTime", startTime);
    commitSetting("agingResult", false);
    doWork();
}

void MainWindow::on_pushButton_2_clicked()
{
    appendLog("手动停止任务");
    stopWork();
}

void MainWindow::on_pushButton_3_clicked()
{
    //判断是否符合报告提交条件
    if(getSetting("agingResult").toBool()){
        uploadReport(true);
    }else{
        int res = QMessageBox::question(nullptr, "警告", "老化未完成，是否仍要提交报告？");
        if(res == QMessageBox::Yes){
            ui->infoBoard->append("老化未完成，仍然提交报告");
            uploadReport(false);
        }else{
            ui->infoBoard->append("不再提交");
        }
    }
}

void MainWindow::on_action_triggered()
{
    qDebug()<<"查看LOG";
    //查看LOG
    QString fileName = QFileDialog::getOpenFileName(this, QString("选择"), ROOT_PATH);
    if(!fileName.isEmpty())
    {
        QProcess *p = new QProcess(this);
        p->startDetached("zenity --width=1280 --height=800 --text-info --filename=" + fileName);
    }
}

void MainWindow::on_action_2_triggered()
{
    //删除日志
    QFile file(QString("%1/aging_log.txt").arg(ROOT_PATH));
    int result = QMessageBox::question(nullptr, "警告", "确认清除日志吗？", QMessageBox::Yes|QMessageBox::No);
    if(result == QMessageBox::Yes){
        if(file.remove()){
            ui->infoBoard->append("日志已清除");
        }else{
            ui->infoBoard->append(file.errorString());
        }
    }
}

void MainWindow::on_action_4_triggered()
{
    //软件信息
    QString sw_name = getSetting("swName").toString();
    QString swVersion = getSetting("swVersion").toString();
    QString product = getSetting("product").toString();
    QMessageBox::information(this, QString("信息"), QString("软件名称：%1\n"
                                                          "软件版本：%2\n"
                                                          "服务于产品：%3\n"
                                                          "开发者：greatwall").arg(sw_name).arg(swVersion).arg(product));
}

//连接测试专用wifi
void MainWindow::on_action_wifi_triggered()
{
    //一体机暂不开放此功能
    QMessageBox::information(this, QString("提示"), QString("此版本暂不开放此功能"));
    return;
    //检查网络环境
    QProcess p;
//    connect(&p, &QProcess::readyRead,[&](){
//        ui->infoBoard->append(p.readAll().simplified());
//    });
    p.start(ROOT_PATH+"/tools/wifiConnect.sh");
    p.waitForFinished();
    if(p.exitCode() == 0){
        ui->infoBoard->append("网络已连接");
    }else{
        ui->infoBoard->append("网络连接失败");
    }
}

//打开配置
void MainWindow::on_action_3_triggered()
{
    settingDlg.loadConfig();
    settingDlg.exec();
}

//预定一次老化
void MainWindow::on_action_5_triggered()
{
    QProcess p;
    p.execute(ROOT_PATH+"/script/reboot/bookOnceAging.sh");
    if(p.exitCode() == 0){
        QMessageBox::warning(nullptr, "提醒", "预定成功，稍后将会自动关机");
    }else{
        QMessageBox::warning(nullptr, "提醒", "未知错误");
    }

}

void MainWindow::on_action_U_triggered()
{
    //一体机暂不开放此功能
    QMessageBox::information(this, QString("提示"), QString("此版本暂不开放此功能"));
}

void MainWindow::on_action_6_triggered()
{
    QProcess::startDetached(ROOT_PATH+"/update.sh");
}
